 # 腾讯证券内容获取

# -使用cookies自动登录
# -以组号在excel中新建一个sheet，命名是当前日（5天）和止盈（1个）
# -依次获取自选股的6个分组，具体见readme
# -sheet定位方法和组名要一致，买入价手动填入
# -不自动定时获取线上腾讯证券信息，改为手动执行脚本，随时可以获取数据
# -第5日后符合止盈策略的复制进止盈sheet
# -循环执行上述流程
# -在表格中记录绘制当前价和刚加入组时价格的涨跌幅百分比曲线（后期）
# -策略具体内容查看及修改见对应函数（太复杂暂时不用宏定义，后期可以）
# 邮箱发送抛出信息和表格

# 需要修改的全局变量或配置：
# 先进行cookies的获取，而且可能需要不定时更新
# 买入和加入组必需同步发生，这样策略时间才准确
# 为了保证当前日名字不冲突，每个月都需要把策略筛选日期外的删除 （后续可以自动删除）
# DAY3_OUT_TARGET # 第3天是否出的盈利点判断 行情好的时候 这个值大一点，行情差的时候小一点，谨慎保本
# stock_url 登录地址
# Check_space 间隔读取时间 分钟
# Stock_data_path 数据保存路径
# stock_templet_path 数据格式保存模板路径
# Chrome_drv_path  浏览器地址
# 新建templet.xlsx文件
# 写入文件的时候需求提前关闭掉
# 不能同时登录两个证券账号 否则需要重新生成cookies 或者用两个浏览器
# 模板格式不能动


import json
import math
import sys

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

import smtplib
import eyed3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from pydub import AudioSegment
import email
import imaplib
import os
import shutil
import time
import traceback
import zipfile
from email.header import decode_header, Header
from email.utils import parseaddr
from pathlib import Path
import datetime
import datedays
from selenium.webdriver.common.keys import Keys
import pandas as pd
import baostock as bs
import eventlet  # 导入eventlet这个模块
from chinese_calendar import is_workday
import numpy as np


DEBUG = 1
PC_COM = 1  # 0-家庭 1-公司

DAY1_OUT_LOSS = 5  # 日跌5点出
DAY3_OUT_LOSS = 3  # 3日跌3点出
DAY5_OUT_LOSS = 5  # 5日跌5点出
DAY3_OUT_TARGET = 1  # 第3天是否出的盈利点判断 行情好的时候 这个值大一点，行情差的时候小一点，谨慎保本
DAY_LAST_OUT_TARGET = 50  # 相对昨日收益率的变化幅度超过-50，则止盈出
DAY_MAX_OUT_TARGET = 50  # 相对最高日收益率的变化幅度超过-50，则止盈出
DAYS_WATCH = 3  # 观察的天数 3-5之间
DAY_RADIO = 1  # 日利率 一天一点

TIMEOUT = 30  # 程序卡死时间和网页等待时间的2倍  单位秒

Stock_url = "https://gu.qq.com/i/#/1/all/mk"  # 检索地址

if PC_COM == 1:
    Stock_data_path = "D:\\video\\tool\\auto_tool\\a money\\strategy"  # 数据保存路径
    Stock_templet_path = "D:\\video\\tool\\auto_tool\\a money\\strategy\\templet.xlsx"  # 模板路径
    Chrome_drv_path = "C:\\Users\\addoi\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe"  # 浏览器地址
else:
    Stock_data_path = "D:\\video\\tool\\auto_tool\\a money\\data"  # 数据保存路径
    Stock_templet_path = "D:\\video\\tool\\auto_tool\\a money\\data\\templet.xlsx"  # 模板路径
    Chrome_drv_path = "C:\\Users\\addoi\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe"  # 浏览器地址

remote_server_url = 'imap.qq.com'
email_url = "3324564761@qq.com"  # 当前使用邮箱
password = "ioaeproulegrchff"
email_msg_to = "1984832368@qq.com"  # 发送邮箱
check_time = 10 # n 秒检测一次是否更新

pc_name = ["com", "fam"] # 运行 pc 环境

rewrite_print = print
def print(*arg):
   rewrite_print(*arg)
   output_dir = "log_file"
   if not os.path.exists(output_dir):
         os.makedirs(output_dir)
   log_name = 'log.txt' # 日志文件名称
   filename = os.path.join(output_dir, log_name)
   rewrite_print(*arg,file=open(filename,"a")) # 写入文件

def print_d(*arg): #仿真调试用
    if DEBUG == 1:
        print('------调试打印开始-----')
        print(*arg)
        print('------调试打印结束-----\r\n')



class doc_function():  # 文件操作
    def save_data_txt(data):  # 添加数据到文件
        info_str = str(data)
        info_str += '\r\n'
        print(info_str)
        with open('flash_tool.log', 'a') as lead:
            lead.write(info_str)

    def set_data(data):  # 重写文件
        data_w = "data  " + data
        fi = open('data.txt', 'w', encoding='utf-8')
        fi.write(data_w)

    def mkdir(path):  # 新建文件夹
        folder = os.path.exists(path)

        if not folder:  # 判断是否存在文件夹如果不存在则创建为文件夹
            os.makedirs(path)  # makedirs 创建文件时如果路径不存在会创建这个路径
            print("---  new folder...  ---")
        else:
            print("folder is:", path)

    def copyfile(srcfile, dstpath):  # 复制文件
        if not os.path.isfile(srcfile):
            print("%s not exist!" % (srcfile))
        else:
            fpath, fname = os.path.split(srcfile)  # 分离文件名和路径
            if not os.path.exists(dstpath):
                os.makedirs(dstpath)  # 创建路径
            shutil.copy(srcfile, dstpath + fname)  # 复制文件

    def file_zip(start_file, zip_dir):  # 压缩文件
        # start_dir 要压缩的文件
        # zip_file 输出zip文件的路径
        fpath_start_dir, fname = os.path.split(start_file)  # 分离文件名和路径

        zip_file = zip_dir + '.zip'
        z = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED)
        print(z)
        for path, dirname, file_name in os.walk(fpath_start_dir):
            # print("文件夹根路径：", path)
            fpath = path.replace(fpath_start_dir, '')  # 去除根路径名称
            # print("--去除根路径：", fpath)
            fpath = fpath and fpath + os.sep  # 在原fpath加上\
            # print("****去除根路径+\ ：", fpath)

            for filename in file_name:  # 逐个循环读取文档名称
                if filename.find(fname) >= 0:
                    # print(filename)
                    z.write(os.path.join(path, filename), fpath + filename)  # 实现在输出路径的Zip压缩操作
        z.close()


    # def get_web():
        # if os.path.isfile("cfg.txt"):
        #     f = open(r"cfg.txt", "r", encoding="utf-8")
        #     data = f.read()
        #     reg = 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
        #     url = re.findall(reg, data)
        #     return url[-1]  # 假如地址在这一行的最后一个位置
        # else:
        #     print(" cfg.txt is not accessible, please creat!!!")
        #     sys.exit()

    def file_unzip_download(unzip_file):
        print(f"开始进行解压缩并下载···")

        zip_file = zipfile.ZipFile(unzip_file)
        fpath, fname = os.path.split(unzip_file)
        out_file = fpath + "\\unzip"
        if os.path.isdir(out_file):
            shutil.rmtree(out_file)
            os.mkdir(out_file)
        else:
            os.mkdir(out_file)
        for names in zip_file.namelist():
            zip_file.extract(names, out_file)
        zip_file.close()
        folder = Path(out_file.strip())
        result = list(folder.rglob(f'*{".hex"}*'))  # 只要hex文件
        print(result[0])  # 默认一个压缩包只有一个文件
        flash_file = str(result[0])
        # 进行文件的各种操作处理
        shutil.rmtree(out_file)

    def search_file(key_word, self_path=None):  # 查找的关键字 self_path是自定义路径
        if self_path != None:
            folder_str = self_path
        else:
            folder_str = os.path.join(os.getcwd(), qq_email_rx.Subject)  # 刘森 新世界

        folder = Path(folder_str.strip())
        # print(folder)
        if folder.exists():
            print("开始根据关键字查找文件···")
        else:
            print("未找到存放关键字对应文件的文件夹")
            return None

        result = list(folder.rglob(f'*{key_word}*'))
        if not result:
            print(f'在{folder} 下未找到关键字名称 {key_word} 的文件夹或文件')
            return None
        else:
            print(f'在{folder} 下找到关键字名称 {key_word} 的文件夹或文件{result}')
            return result

    def get_stock_code():  # 获取股票代码
        df = pd.read_excel(Stock_code_path, sheet_name=0, dtype={0:"string"})
        code_list = df["stock_code"].tolist()

        # 去掉中间的空项
        res = []
        for val in code_list:
            if str(val) != '<NA>':
                res.append(str(val))

        return res

    def get_str_row_column(words): #获取字符串中行数和列的最大字符数，返回两者的最大值
        row = words.count("\n") + 1

        # 存储所有的相同字符之间的距离
        length = []
        loc = 0
        last_loc = 0

        while words.find("\n", loc+1) != -1:
            loc = words.find("\n", loc+1)

            length.append(loc - last_loc)
            last_loc = loc

        length.append(len(words) - last_loc) # 获取最后一行长度
        # print(length)
        # print(f'最大长度：{max(length)}')
        column = max(length)
        # print(max(row, column))
        return max(row, column)

    def delete_files(file_path):
        if os.path.exists(file_path):
            shutil.rmtree(file_path)
            return True
        else:
            # file not found message
            print(f'要删除的文件夹{file_path}找不到')
            return False

    def cookie_creat(pc_name = pc_name[0]):  # 生成cook platform是投稿平台 pc_name是哪个pc
        path = Service(Chrome_drv_path)
        web = webdriver.Chrome(service=path)
        web.get(Stock_url)

        web.delete_all_cookies()  # 先删除cookies
        time.sleep(60)  # 这个时间用于手动登录,扫码登录可以适当缩短这个等待时间
        dictcookies = web.get_cookies()  # 读取登录之后浏览器的cookies
        jsoncookies = json.dumps(dictcookies)  # 将字典数据转成json数据便于保存

        path_keyword = pc_name
        search_path = os.path.join(os.getcwd(), "cookies")
        doc_function.mkdir(search_path)
        save_name = search_path + "\\" + path_keyword + ".txt"
        print_d(save_name)

        with open(save_name, 'w') as f:  # 写进文本保存
            f.write(jsoncookies)
        print('cookie is ok')

    def cookie_use(pc_name = pc_name[0]):  # 使用cookie进行登录 返回web
        path = Service(Chrome_drv_path)
        web = webdriver.Chrome(service=path)
        web.implicitly_wait(TIMEOUT/2)  # 隐性等待，最长等TIMEOUT/2秒

        web.get(Stock_url)

        path_keyword = pc_name
        search_path = os.path.join(os.getcwd(), "cookies")
        cook_name = search_path + "\\" + path_keyword + ".txt"

        if os.path.isfile(cook_name):
            f = open(cook_name, 'r')
            listcookie = json.loads(f.read())  # 读取文件中的cookies数据

            for cookie in listcookie:
                web.add_cookie(cookie)  # 将cookies数据添加到浏览器
            return web
            # web.refresh()  # 刷新网页
        else:
            # print("不存在此文件", cook_name)
            return web

        # input()  # 暂时暂停 否则一闪而过 后面有内容了再去掉

    def add_row_to_excel(row_data, sheet_name, excel_path, day_num=None): # 向excel中新加一行数据  row_data：行数据  sheet_name: sheet名字 excel_pat：路径 day_num: 日期对应的行号
        # print_d(row_data)
        df = pd.read_excel(excel_path, header=0, sheet_name=sheet_name)  # 读入数据
        if day_num == None:  # 一直向下新增
            df_all = pd.DataFrame(data=None)  # 创建空的 dataframe
            # 多数据做循环处理即可
            df_all = pd.concat([df_all, df], ignore_index=True)  # concat 合并有相同字段名的dataframe
            df = pd.DataFrame(row_data)
            df_all = pd.concat([df_all, df], ignore_index=True)

            data_list = df_all.drop_duplicates(keep='first')  # 避免字段名重复写入，一般会做去重处理
            df_all.to_excel(excel_path, index=False, sheet_name=sheet_name, encoding='utf-8')  # 写出数据
        else:  # 向某一行写入，如果有则覆盖
            targrt = row_data
            day_row_num = day_num + 1  # 第1天对应的行号是2

            df_dict = df.to_dict()
            # print("修改前当日信息", df_dict)

            for i in range(0, len(targrt)):
                i = int(i)
                key = list(targrt.keys())[i]  # 获取要修改的key
                try:
                    df_dict[key][day_row_num] = targrt[key][0]  # 重新赋值
                except:  # 格式发生变化
                    df_dict[int(key)][day_row_num] = targrt[key][0]  # 重新赋值

            # print("修改后当日信息", df_dict)

            df_all = pd.DataFrame(df_dict)
            with pd.ExcelWriter(excel_path, mode='a', if_sheet_exists='replace') as writer:
                df_all.to_excel(writer, index=False, sheet_name=sheet_name)

    def creat_excel_sheet(sheet_name, stock_code_list, stock_name_list): # 创建excel的sheet模板 sheet_name：表格名字   columns：列数 stock_code_list代码列表  stock_name_list名字列表
        pd_dict = {'时间': ['初次买入时间', '初次买入价格', '第1天开盘', '第2天开盘', '第3天开盘', '第4天开盘', '第5天开盘', '第6天开盘']}  # excel 数据组包
        d_buy = datetime.date(int(datetime.datetime.now().year), int(datetime.datetime.now().month), int(sheet_name))

        columns = len(stock_code_list)
        for i in range(0, columns):
            buy_time = str(d_buy)
            pd_dict[f'{stock_code_list[int(i)]}'] = [buy_time, "", "", "", "", "", "", ""]
            pd_dict[f'{stock_name_list[int(i)]}'] = [buy_time, "", "", "", "", "", "", ""]

        # print_d(pd_dict)
        stock_signal_data = pd.DataFrame(pd_dict)
        try:
            with pd.ExcelWriter(Stock_templet_path, mode='a', engine='openpyxl') as writer:
                stock_signal_data.to_excel(writer, sheet_name=sheet_name)
        except:
            # print(sheet_name, "sheet文件已经存在且初始化")
            df = pd.read_excel(Stock_templet_path, sheet_name=sheet_name, dtype={0: "string"})
            row_column_num = df.shape
            # print_d(row_column_num, columns)
            if ( row_column_num[1] - 2 ) / 2 < columns:  # 线上有新增 则新插入
                print(sheet_name, "有股票新增！！！")
                df_dict = df.to_dict()
                print("修改前当日信息", df_dict)
                df_dict[f'{stock_code_list[int(columns - 1)]}'] = {0:buy_time, 1:"", 2:"", 3:"", 4:"", 5:"", 6:"", 7:""}
                df_dict[f'{stock_name_list[int(columns - 1)]}'] = {0:buy_time, 1:"", 2:"", 3:"", 4:"", 5:"", 6:"", 7:""}
                print("修改后当日信息", df_dict)

                df_all = pd.DataFrame(df_dict)
                with pd.ExcelWriter(Stock_templet_path, mode='a', if_sheet_exists='replace') as writer:
                    df_all.to_excel(writer, index=False, sheet_name=sheet_name)




class web_tx_parse:  # 腾讯的网页处理
    def __init__(self, pc):
        self.pc_name = pc   # pc_name[0] - com;   [1] - fam
        self.web = None

    def log_on(self):  # 登录
        print("登录中")
        web = doc_function.cookie_use(self.pc_name)
        web.refresh()  # 必需在这刷新，否则闪退
        self.web = web
        time.sleep(3)
        self.web.find_elements(By.XPATH, '/html/body/div[5]/div/div[3]')[0].click() # 将 我知道 点掉
        time.sleep(1)


    def data_signal(self, group_str):  # 单组（1-5，止盈）数据获取  group:组web元素
        group = self.web.find_elements(By.XPATH, group_str)[0]
        print("\r\n", self.pc_name, "-组信息获取中-组名：", group.text)

        sheet_name = group.text
        stock_data_list = []  # 数据
        stock_code_list = []  # 代码
        stock_name_list = []  # 名字
        stock_new_list = []  # 最新价
        stock_open_list = []  # 开盘

        # 获取股票信息 代码 名字 最新价 今开
        group.click()
        time.sleep(2)  # 必需等待
        stock_name = self.web.find_elements(By.XPATH, '//*[@id="zxg-body"]/div[5]')[0].text
        stock_data_list = stock_name.split()
        # print_d(len(stock_data_list))
        stock_num = len(stock_data_list)/14   # 一组数据是14个
        stock_num = int(stock_num)
        if stock_num == 0:
            print(sheet_name, "-组中没有发现股票信息")
            return None

        for i in range(0, stock_num): # 目前一组数据是14个元素
            num = i * 14
            stock_code_list.append(stock_data_list[0+num])
            stock_name_list.append(stock_data_list[1+num])
            stock_new_list.append(stock_data_list[2+num])
            stock_open_list.append(stock_data_list[6+num])


        if sheet_name != "止盈": # 短线策略
            print("开始进行短线止损策略匹配")
            days_work = stock_parse.get_days_now_buy(sheet_name, stock_code_list[0])  # 获取今天是第几天
            # print(days_work)
            if days_work == 0:
                print("此为初次创建表格，请确认已填入买入价!!!\r\n 不进行策略匹配，次日进行")
                # 初次创建表格
                doc_function.creat_excel_sheet(sheet_name, stock_code_list, stock_name_list)
            elif days_work < 5 and days_work > 0:
                # 进行表格填入及策略匹配
                result = stock_parse.update_stock_excel(sheet_name, stock_code_list, stock_name_list, stock_new_list, stock_open_list)
                if result == None:
                    return None
                # print("进入按日策略匹配")
                stock_parse.stop_loss(Stock_templet_path, str(sheet_name), stock_new_list, stock_code_list)
            else:
                print(f'组{sheet_name}的时间{days_work}不对，请处理组内股票!!!')
                return None

        else:  # 止盈中的前面数据手动从sheet中复制过来  根据初次买入时间计算应该填入哪一列
            print("开始进行短线止盈策略匹配")
            buy_list = stock_parse.update_stock_excel(sheet_name, stock_code_list, stock_name_list, stock_new_list, stock_open_list)  # 返回成本列表
            if buy_list == None:
                return None
            stock_parse.target_profit(str(sheet_name), stock_new_list, stock_code_list, buy_list)

        # 暂时无邮箱通知

        # input()

        # 直接组包 写入

    def get_groups(self):  # 获取及排序5组元素和止盈元素
        # //*[@id="zxg-body"]/div[4]/div[1]/div/ul/li[2]/div
        group_xpath_list = []
        stock_xpath_tp = ""  # 止盈票
        print("元素获取及分组中···")
        for num in range(2, DAYS_WATCH+4): # 检索2-8
            xpath = "//*[@id=\"zxg-body\"]/div[4]/div[1]/div/ul/li[" + str(num) + "]/div"
            try:
                data = self.web.find_elements(By.XPATH, xpath)[0]
            except:
                print("未找到元素：", num, "继续查找元素")
                continue

            data_num = data.text
            if data_num.isdigit(): # 只进行数字组的获取
                group_xpath_list.append(xpath)
            else:
                stock_xpath_tp = xpath

        if stock_xpath_tp == "":
            print("未发现止盈分组，请检查分组及排序！！！")
        else:
            group_xpath_list.append(stock_xpath_tp)  # 最后存放止盈的元素

        if len(group_xpath_list) < (DAYS_WATCH + 2):
            print(f'股票有效分组数量或排序不对，应为总{(DAYS_WATCH + 2)}个，命名{(DAYS_WATCH + 1)}个数字，1个止盈！！！' )

        # print("股票分组列表xpath", group_xpath_list)  #
        return group_xpath_list


    def data_all(self):  # 获取所有的数据信息
        if stock_parse.stock_work_day() == False:
            return None

        eventlet.monkey_patch()  # 必须加这条代码
        group_xpath_list = stock_get.get_groups()

        for group_xpath in group_xpath_list:
            try:
                with eventlet.Timeout(TIMEOUT, False):  # 设置超时时间为30秒
                    try:
                        stock_get.data_signal(group_xpath)
                        time.sleep(1)
                        # 该语句正常执行
                    except Exception:
                        print(f'-------进行信息检查{group_xpath}出错!!! 可能原因是excel已经被打开-----\r\n')
            except Exception:
                print("----时间处理超时!!!-----")

            # break  # 后续去掉


    def quit(self):  # 退出
        print(self.pc_name, "退出中")
        self.web.quit()



class stock_parse:  # 股票处理
    def __init__(self, data_path):
        self.data_path = data_path

    def is_trade_day(date):  # 得到当前日期是否为股票交易日
        if is_workday(date):
            if date.isoweekday() < 6:
                return True
        return False

    def stock_work_day(group_name = None): # 判断现在是否是交易时间 或者获取下一个工作日
        if group_name == None: # 判断当前时间是否是交易时间
            data_temp = time.strftime('%Y-%m-%d', time.localtime())
            data = datetime.datetime.strptime(data_temp, '%Y-%m-%d').date()
            if stock_parse.is_trade_day(data) == False:
                print("非交易日期")
                return True
            elif datetime.datetime.now().hour < 9 or datetime.datetime.now().hour > 15: # 15
                print("非交易时间")
                return True
            else:
                print("交易时间,开始进行数据获取")
                return True
        else: # 判断组号所代表的那一天是否是交易日
            days_num = 1
            while stock_parse.is_trade_day(datedays.gettomorrow(days=days_num)) == False:
                days_num = days_num + 1

            return str(datedays.gettomorrow(days=days_num))[-2:]  # 返回下一个组名


    def get_stock_codes(date=None): # 获取指定日期的A股代码列表  stock_codes = get_stock_codes()
        """
        获取指定日期的A股代码列表

        若参数date为空，则返回最近1个交易日的A股代码列表
        若参数date不为空，且为交易日，则返回date当日的A股代码列表
        若参数date不为空，但不为交易日，则打印提示非交易日信息，程序退出

        :param date: 日期
        :return: A股代码的列表
        """

        # 登录baostock
        bs.login()

        # 从BaoStock查询股票数据
        stock_df = bs.query_all_stock(date).get_data()

        # 如果获取数据长度为0，表示日期date非交易日
        if 0 == len(stock_df):

            # 如果设置了参数date，则打印信息提示date为非交易日
            if date is not None:
                print('当前选择日期为非交易日或尚无交易数据，请设置date为历史某交易日日期')
                sys.exit(0)

            # 未设置参数date，则向历史查找最近的交易日，当获取股票数据长度非0时，即找到最近交易日
            delta = 1
            while 0 == len(stock_df):
                stock_df = bs.query_all_stock(datetime.date.today() - datetime.timedelta(days=delta)).get_data()
                delta += 1

        # 注销登录
        bs.logout()

        # 筛选股票数据，上证和深证股票代码在sh.600000与sz.39900之间
        stock_df = stock_df[(stock_df['code'] >= 'sh.600000') & (stock_df['code'] < 'sz.399000')]

        # 返回股票列表
        return stock_df['code'].tolist()

    def stop_loss(data_path = Stock_templet_path, sheet_name=None, new_list=None, code_list=None): # 止损策略 data_path：excel路径  多日间价格差使用开盘价  days_work:判断今天是第几天 stock_new_list:最新价格
        # print(data_path)
        df = pd.read_excel(data_path, header=0, sheet_name=sheet_name)  # 读入数据
        df_dict = df.to_dict()

        # 有一天建议抛出也要抛出
        # 日跌5点判断
        stock_parse.radio_day_cal(1, sheet_name, df_dict, code_list, new_list)
        # 3日3点判断
        stock_parse.radio_day_cal(3, sheet_name, df_dict, code_list, new_list)


        # 下面两个功能可以用腾讯自选股实现
        # 计算今日总收益率 今日总收益和总持有的比值
        # 所有策略股总收益率  一直累加计算总收益和总持有的比值


    def target_profit(sheet_name=None, new_list=None, code_list=None, buy_list=None): # 止盈策略
        # print(data_path)
        df = pd.read_excel(Stock_templet_path, header=0, sheet_name=sheet_name)  # 读入数据
        df_dict = df.to_dict()

        # 同样需要止损判断
        stock_parse.stop_loss(Stock_templet_path, str(sheet_name), new_list, code_list)
        # 5日5点判断
        stock_parse.radio_day_cal(5, sheet_name, df_dict, code_list, new_list)
        # 总收益判断
        stock_parse.radio_sum_cal(sheet_name, df_dict, code_list, new_list, buy_list)



    def radio_day_cal(last_day, sheet_name, df_dict, code_list, new_list): # 计算当前和第前last_day天的收益率
        i = 0
        days_work = stock_parse.get_days_now_buy(sheet_name, code_list[0])  # 判断非止盈分组是否多余
        if days_work > DAYS_WATCH and sheet_name != "止盈":
            print(f'此为第{days_work}天，已经超过止损观察的{DAYS_WATCH}天，请移除并删除分组！！！！')

        for code in code_list:  # 位置获取
            # 获取当前和买入日间隔时间
            days_work = stock_parse.get_days_now_buy(sheet_name, code)
            if (days_work - last_day >= -1) and (days_work > 2 or last_day == 1):  # 上一天的天数大于-1 因为是以第n天开盘记作第n-1天的收盘
                day_row_num = days_work - last_day + 2  # 第1天对应的行号是2 第0天对应的买入价格
            else:  # 例 第1天的上三天或上三天不成立 第1天的上一天是第0天，即对应的买入价格
                print(f'第{days_work}天的上{last_day}天不存在!!!')
                return None

            try:
                open = df_dict[code][day_row_num]  # n日开盘
            except: # 格式发生变化
                open = df_dict[int(code)][day_row_num]  # n日开盘
            new = new_list[i]
            i = i + 1
            radio = ((float(new) - float(open)) / float(open)) * 100
            radio = round(radio, 2)
            if math.isnan(radio) == True:
                print(f'以下为止损策略结果：股票代码{code}相对第{last_day}天收益率未填入！！！！！')
                return None

            print(f'以下为止损策略结果：股票代码{code}相对前{last_day}天收益率为{radio}%')

            if last_day == 1: # 日跌5点判断
                if radio <= -DAY1_OUT_LOSS:
                    print(f'建议抛出（日跌{DAY1_OUT_LOSS}点）！！！！！')
                else:
                    print("建议持有")
            elif last_day == 3 and days_work > 3: # 3日3点判断
                # print(days_work)
                if radio <= -DAY3_OUT_LOSS:
                    print(f'建议抛出（日跌{DAY3_OUT_LOSS}点）！！！！！')
                else:
                    print("建议持有")
            elif last_day == 3 and days_work == 3: # 第3日没有收益出
                if radio <= DAY3_OUT_TARGET:  # 行情好的时候 这个值大一点，行情差的时候小一点，谨慎保本
                    print(f'建议抛出（三日预期不足{DAY3_OUT_TARGET}点）！！！！！')
                else:
                    print(f'建议持有，且将股票移入止盈策略（三日预期超出{DAY3_OUT_TARGET}点）！！！！！')
            elif last_day == 5: # 5日5点判断
                if radio <= -DAY5_OUT_LOSS:
                    print(f'建议抛出（日跌{DAY5_OUT_LOSS}点）！！！！！')
                else:
                    print("建议持有")

    def radio_sum_cal(sheet_name, df_dict, code_list, new_list, buy_list): # 通过总收益率的变化决定是否出  buy_list:成本价
        # 当前总收益率是否低于昨日的一半
        i = 0

        for code in code_list:  # 位置获取
            # 获取今日位置
            days_work = stock_parse.get_days_now_buy(sheet_name, code)
            target_days = days_work - DAYS_WATCH  # 加入止盈的天数
            if target_days <= 0:
                print(f'代码{code}加入止盈的天数不够{DAYS_WATCH+1}天！！！')
                continue

            day_row_num = days_work + 1  # 第1天对应的行号是2

            try:
                open = df_dict[code][day_row_num]  # n日开盘
            except: # 格式发生变化
                open = df_dict[int(code)][day_row_num]  # n日开盘
            new = float(new_list[i])  # 最新价
            open = float(open)
            # 当前总收益率是否低于昨日的一半  昨日收益计算使用（今日开盘-成本）/ 成本  * 100
            # print(buy_list[0], last_radio, open_list[0], day_row_num)
            stock_buy = float(buy_list[i])  # 成本价格
            radio = ((new - stock_buy) / stock_buy) * 100  # 最新收益率
            radio = round(radio, 2)
            # last_radio = (open - stock_buy) / stock_buy * 100
            # last_radio = round(last_radio, 2)
            #
            # if math.isnan(radio) == True or math.isnan(last_radio) == True:
            #     print(f'以下为策略结果：股票代码{code}相对昨天收益率未填入！！！！！')
            #     return None

            # d_radio = (radio - last_radio) / last_radio * 100  # 收益率差值
            # if last_radio < 0 and d_radio < 0:
            #     d_radio = -d_radio
            # d_radio = round(d_radio, 2)
            # print(f'以下为止盈策略结果：股票代码{code}最新收益率{radio}%相对昨日累计{last_radio}%变化{d_radio}%')
            # if d_radio <= -DAY_LAST_OUT_TARGET:
            #     print(f'建议抛出(相对昨天收益降低超过{DAY_LAST_OUT_TARGET}点)！！！！！')
            # else:
            #     print("建议持有")

            # 当前总收益率是否低于最高收益的一半
            value_list = list(df_dict[code_list[i]].values())
            value_list = value_list[2:(days_work+2)]
            for num in range(0, len(value_list)):  # 转换为整型
                value_list[num] = float(value_list[num])
            # print_d("开盘价格表", value_list)
            max_radio = (max(value_list) - stock_buy) / stock_buy * 100  # 最高收益计算使用（最高开盘-成本）/成本 * 100
            max_radio = round(max_radio, 2)
            # print("历史最高收益率为：", last_radio)
            d_radio = (radio - max_radio) / max_radio * 100 # 收益率差值
            d_radio = round(d_radio, 2)

            if radio >= days_work * DAY_RADIO:  # 最新总收益率大于持有天数
                print(f'以下为止盈策略结果：股票代码{code}最新收益率{radio}%相对历史最高{max_radio}%变化{d_radio}%')
                if d_radio <= -DAY_MAX_OUT_TARGET:  # 若跌后总收益低于历史最高总收益的一半则出
                    print(f'建议抛出(相对最高收益降低超过{DAY_MAX_OUT_TARGET}点)！！！！！')
                else:
                    print("建议持有")
            elif radio > target_days * DAY_RADIO:  # 在加入止盈n天（总天数-止损观察的3天）后收益率大于n点则一直持有 DAY_RADIO = 1
                print(f'以下为止盈策略结果：股票代码{code}加入止盈{target_days}天后最新收益率{radio}%达到{target_days * DAY_RADIO}%')
                print("建议持有")
            else:
                print(f'以下为止盈策略结果：股票代码{code}加入止盈{target_days}天后最新收益率{radio}%未达到{target_days * DAY_RADIO}%')
                print(f'建议抛出！！！！！')

            i = i + 1

    def get_days_now_buy(sheet_name, code):  # 获取某sheet某票code今日和买入日的时间
        try:
            df = pd.read_excel(Stock_templet_path, header=0, sheet_name=sheet_name)  # 读入数据
        except:  # 出现错误说明这个文件还不存在
            return 0

        stock_title = df.columns.values
        stock_title_str = "".join('%s-' % a for a in stock_title)
        if stock_title_str.find(str(code)) == -1:  # 没有发现这只票 认为数据对不上
            print("线上分组和表格code内容对不上，找不到代码：", code, "-不进行持有时间计算，请核对！！！")
            return None

        df_dict = df.to_dict()
        try:
            data = df_dict[str(code)][0]  # 日期位置固定 第0行
        except: # 文本格式发生改变
            data = df_dict[int(code)][0]

        data = data.split('-')
        d_buy = datetime.date(int(data[0]), int(data[1]), int(data[2]))
        d_now = datetime.date(int(datetime.datetime.now().year), int(datetime.datetime.now().month),
                              int(datetime.datetime.now().day))
        days_work = np.busday_count(d_buy, d_now)

        return int(days_work)

    def update_stock_excel(sheet_name, stock_code_list, stock_name_list, stock_new_list, stock_open_list):  # 根据获取到的线上信息更新excel
        # print_d(stock_code_list, stock_name_list, stock_new_list, stock_open_list)
        try:
            df = pd.read_excel(Stock_templet_path, sheet_name=sheet_name, dtype={0: "string"})
        except:
            print(sheet_name, "sheet读取失败！！！ 开始新建···")
            doc_function.creat_excel_sheet(sheet_name, stock_code_list, stock_name_list)
            return None
        stock_title = df.columns.values
        stock_title_str = "".join('%s-' % a for a in stock_title)
        for code in stock_code_list:
            if stock_title_str.find(str(code)) == -1:  # 没有发现这只票 认为数据对不上
                print("线上分组和表格内容对不上，找不到代码：", code, "-不进行策略匹配，请核对！！！")
                return None

        # pd_dict = dict()
        df_dict = df.to_dict()
        buy_list = []
        i = 0
        for code in stock_code_list:
            pd_dict = dict()
            try:
                stock_buy = df_dict[code][1]  # 买入价
            except: # 格式发生变化
                stock_buy = df_dict[int(code)][1]  # 买入价

            # print_d(stock_buy)
            buy_list.append(stock_buy)

            try:
                stock_buy_price = float(stock_buy)  # 买入
                radio = (float(stock_new_list[int(i)]) - stock_buy_price) / (stock_buy_price) * 100  # 计算总收益率百分比
                radio = round(radio, 2)
                # print_d(radio, stock_new_list[int(i)], stock_buy_price)
            except:
                print(sheet_name, "未找到买入价格，请填入!!!")
                return None

            pd_dict[f'{stock_code_list[int(i)]}'] = [str(stock_open_list[int(i)])]  # 开盘
            pd_dict[f'{stock_name_list[int(i)]}'] = [f'{radio}%']  # 和买入时的百分比差

            days_work = stock_parse.get_days_now_buy(sheet_name, code)
            # print(pd_dict, buy_list)
            doc_function.add_row_to_excel(pd_dict, str(sheet_name), Stock_templet_path, days_work)  # 修改为不是向下加一行，而是是第几天在那一天对应行上加上

            i = i + 1

        return buy_list  # 成本价格列表

if __name__ == "__main__":
    print("stock for money !!!!")
    # doc_function.cookie_creat()
    stock_get = web_tx_parse(pc_name[0])
    stock_get.log_on()
    try:
        stock_get.data_all()
        stock_get.quit()
        print(f'策略检查结束！！！\r\n')
    except:
        print(f'\r\n策略检查出现错误！！！\r\n')
        traceback.print_exc()








